package org.egomsl.mw.segment;

import org.egomsl.mw.Constants;
import org.egomsl.mw.block.Block;
import org.egomsl.mw.block.BlockImpl;
import org.egomsl.mw.record.Record;

import java.util.LinkedList;
import java.util.concurrent.locks.ReentrantLock;

public class MutableSegment {
    /**
     * 块大小限制
     */
    private int maxBlock;

    private Block currentBlock;

    private ReentrantLock snapshotLock;

    private LinkedList<Block> blocks;

    public MutableSegment() {
        this(Constants.MAX_BLOCK);
    }

    public MutableSegment(int maxBlock) {
        this(maxBlock, Constants.BLOCK_SIZE);
    }

    public MutableSegment(int maxBlock, int blockSize) {
        this.maxBlock = maxBlock;
        this.currentBlock = new BlockImpl(blockSize);
        this.snapshotLock = new ReentrantLock();
        this.blocks = new LinkedList<>();
    }

    public ImmutableSegment snapshot() {
        snapshotLock.lock();

        currentBlock.finalize();
        blocks.addFirst(currentBlock);
        ImmutableSegment snapshot = new ImmutableSegment(blocks);

        currentBlock = new BlockImpl();
        blocks = new LinkedList<>();

        snapshotLock.unlock();

        return snapshot;
    }

    public boolean add(Record record) {
        snapshotLock.lock();
        if(!currentBlock.add(record)) {
            currentBlock.finalize();
            blocks.addFirst(currentBlock);
            currentBlock = new BlockImpl();
            currentBlock.add(record);
        }
        snapshotLock.unlock();

            //reach max block count, should flush to disk
        if(blocks.size() >= maxBlock) {
            return false;
        }

        return true;
    }

    public int getTotalSize() {
        int size = 0;
        for(Block block : blocks) {
            size += block.getLength();
        }
        return size;
    }

}
